package com.shawn.spring.boot.redis.service.impl;

import static org.springframework.data.domain.ExampleMatcher.GenericPropertyMatchers.exact;

import com.shawn.spring.boot.redis.entity.CoffeeEntity;
import com.shawn.spring.boot.redis.repository.CoffeeRepository;
import com.shawn.spring.boot.redis.service.CoffeeService;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

/**
 * @author shawn
 * @since 2020/9/4
 */
@Slf4j
@Service
public class CoffeeServiceImpl implements CoffeeService {

  private static final String CACHE = "coffee";
  @Autowired private CoffeeRepository coffeeRepository;
  @Autowired private RedisTemplate<String, CoffeeEntity> redisTemplate;

  @Override
  public List<CoffeeEntity> findAllCoffee() {
    return coffeeRepository.findAll();
  }

  @Override
  public Optional<CoffeeEntity> findOneCoffee(String name) {
    HashOperations<String, String, CoffeeEntity> hashOperations = redisTemplate.opsForHash();
    if (redisTemplate.hasKey(CACHE) && hashOperations.hasKey(CACHE, name)) {
      log.info("Get coffee {} from Redis.", name);
      return Optional.of(hashOperations.get(CACHE, name));
    }
    ExampleMatcher matcher = ExampleMatcher.matching().withMatcher("name", exact().ignoreCase());
    Optional<CoffeeEntity> coffee =
        coffeeRepository.findOne(Example.of(CoffeeEntity.builder().name(name).build(), matcher));
    log.info("Coffee Found: {}", coffee);
    if (coffee.isPresent()) {
      log.info("Put coffee {} to Redis.", name);
      hashOperations.put(CACHE, name, coffee.get());
      redisTemplate.expire(CACHE, 1, TimeUnit.MINUTES);
    }
    return coffee;
  }
}
